#pragma once
#include "mysql.hpp"
#include "chat_session-odb.hxx"
#include "chat_session_member.hxx"
#include "log.hpp"

#include <vector>
class ChatSessionTable {
public:
    using ptr = std::shared_ptr<ChatSessionTable>;
    using query_cs_t = odb::query<ChatSession>;
    using query_csm_t = odb::query<ChatSessionMember>;

    ChatSessionTable(const std::shared_ptr<odb::core::database> &db) : _db(db) {}
    
    bool insert(ChatSession cs) {
        try {
            odb::transaction trans(_db->begin());
            _db->persist(cs);
            trans.commit();
        }
        catch (const odb::exception &e) {
            LOG_ERROR("插入聊天会话失败: {}:{}", cs.chat_session_name(), e.what());
            return false;
        }
        LOG_INFO("插入聊天会话成功: {}", cs.chat_session_name());
        return true;
    }


    // 移除该会话
    bool remove(const std::string &chat_session_id) {
        try {
            odb::transaction trans(_db->begin());
            _db->erase_query<ChatSession>(query_cs_t::chat_session_id == chat_session_id);
            _db->erase_query<ChatSessionMember>(query_csm_t::chat_session_id == chat_session_id);
            trans.commit();
        }
        catch (const odb::exception &e) {
            LOG_ERROR("删除聊天会话失败: {}:{}", chat_session_id, e.what());
            return false;
        }
        LOG_INFO("删除聊天会话成功: {}", chat_session_id);
        return true;
    }


    // 移除某个单聊会话
    bool remove(const std::string &user_id, const std::string &peer_id) {
        try {
            odb::transaction trans(_db->begin());
            using query_t = odb::query<SingleChatSession>;
            SingleChatSession* r = _db->query_one<SingleChatSession>(
                query_t::csm1::user_id == user_id && 
                query_t::csm2::user_id == peer_id && 
                query_t::css::chat_session_type == ChatSessionType::SINGLE);
            if(!r) {
                LOG_ERROR("删除单聊会话失败: {}-{}:会话不存在", user_id, peer_id);
                return false;
            }

            _db->erase_query<ChatSession>(query_cs_t::chat_session_id == r->_chat_session_id);
            _db->erase_query<ChatSessionMember>(query_csm_t::chat_session_id == r->_chat_session_id);
            trans.commit();
        }
        catch (const odb::exception &e) {
            LOG_ERROR("删除单聊会话失败: {}-{}:{}", user_id, peer_id, e.what());
            return false;
        }
        LOG_INFO("删除单聊会话成功: {}-{}", user_id, peer_id);
        return true;
    }


    // 获取会话id的元信息
    std::shared_ptr<ChatSession> select(const std::string &chat_session_id) {
        std::shared_ptr<ChatSession> res;
        try {
            odb::transaction trans(_db->begin());
            res.reset(_db->query_one<ChatSession>(query_cs_t::chat_session_id == chat_session_id));
            trans.commit();
        }catch (const odb::exception &e) {
            LOG_ERROR("通过会话ID获取会话信息失败 {}:{}!", chat_session_id, e.what());
        }
        return res;
    }


    // 获取用户的所有单聊会话
    std::vector<SingleChatSession> singleChatSession(const std::string &uid) {
        std::vector<SingleChatSession> ret;
        try {
            odb::transaction trans(_db->begin());
            using query_t = odb::query<SingleChatSession>;
            using result_t = odb::result<SingleChatSession>;
            result_t r = _db->query<SingleChatSession>(query_t::csm1::user_id == uid);
            for (const auto &i : r)
                ret.emplace_back(i);
            trans.commit();
        }
        catch (const odb::exception &e) {
            LOG_ERROR("通过用户ID获取单聊会话失败 {}:{}!", uid, e.what());
            return {};
        }
        return ret;
    }


    // 获取用户的所有群聊会话
    std::vector<GroupChatSession> groupChatSession(const std::string &uid) {
        std::vector<GroupChatSession> ret;
        try {
            odb::transaction trans(_db->begin());
            using query_t = odb::query<GroupChatSession>;
            using result_t = odb::result<GroupChatSession>;
            result_t r = _db->query<GroupChatSession>(query_t::csm::user_id == uid);
            for (const auto &i : r)
                ret.emplace_back(i);
            trans.commit();
        }
        catch (const odb::exception &e) {
            LOG_ERROR("通过用户ID获取群聊会话失败 {}:{}!", uid, e.what());
            return {};
        }
        LOG_DEBUG("通过用户ID获取群聊会话成功 {}:{}", uid, ret.size());
        return ret;
    }

private:
    std::shared_ptr<odb::core::database> _db;
};